/* 
 * Copyright (c) 2012, Fromentin Xavier, Schnell Michaël, Dervin Cyrielle, Brabant Quentin
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *      * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *      * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *      * The names of its contributors may not be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Fromentin Xavier, Schnell Michaël, Dervin Cyrielle OR Brabant Quentin 
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package kameleon.gui.view;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JRadioButton;

import kameleon.exception.FileReadingException;
import kameleon.exception.KameleonException;
import kameleon.gui.exception.UnknownKeyException;
import kameleon.gui.language.SwitchLanguage;
import kameleon.gui.model.Model;
import kameleon.gui.util.LanguageConstants;
import kameleon.plugin.PlugInInfo;

/**
 * Frame used by the user to select the analyzer plug-ins that should
 * be used to analyze the currently selected file.
 * 
 * @author		Fromentin Xavier, Schnell Michaël
 * @version		1.0
 */
public class EntryFormatSelectionFrame extends JDialog 
implements LanguageConstants {

	/**
	 * Needed to serialize this class.
	 * 
	 * @see		java.io.Serializable
	 */
	private static final long serialVersionUID = -3340379870384270462L ;
	
	/**
	 * Model of this view.
	 */
	protected Model model ;
	
	/**
	 * The selected analyzer.
	 */
	protected PlugInInfo selectedAnalyzer ;
	
	/**
	 * Validate button.
	 */
	protected JButton validate ;
	
	/**
	 * Sole constructor.
	 * 
	 * @param	container
	 * 			parent frame of this instance
	 * 
	 * @param	model
	 * 			model of this view
	 * 
	 * @throws	KameleonException
	 * 			if an error occurred while build this instance
	 */
	public EntryFormatSelectionFrame(JFrame container, Model model) 
		throws KameleonException {
		super(container, true) ;
		this.model = model ;
		this.selectedAnalyzer = this.model.getCurrentFileFormat() ;
		
		this.setTitle(SwitchLanguage.getInstance()
				.getText(ENTRY_FORMAT_TITLE)) ;
		this.build() ;
		
		this.pack() ;
		this.setResizable(false) ;
		this.setLocationRelativeTo(container) ;
	}// EntryFormatSelectionFrame(JFrame, Model)
	
	/**
	 * Builds the content of this frame.
	 * 
	 * @throws	UnknownKeyException
	 * 			if a key for a displayed text could not be found
	 */
	private void build() throws UnknownKeyException {
		GridBagLayout gridbag = new GridBagLayout() ;
		this.setLayout(gridbag) ;
		
		this.buildTitle(gridbag) ;
		this.buildAnalyzers(gridbag) ;
		this.buildButton(gridbag) ;
	}// build()
	
	/**
	 * Builds the introduction sentence displayed in this frame.
	 * 
	 * @param	gridbag 
	 * 			layout manager used by this frame
	 * 
	 * @throws	UnknownKeyException 
	 * 			if the key for the explanation text was not found
	 */
	private void buildTitle(GridBagLayout gridbag) 
			throws UnknownKeyException {
		SwitchLanguage sl = SwitchLanguage.getInstance() ;
		GridBagConstraints constraints ;
		
		constraints = new GridBagConstraints() ;
		constraints.gridwidth = GridBagConstraints.REMAINDER ;
		constraints.anchor = GridBagConstraints.BASELINE ;
		constraints.weightx = 1.0 ;
		constraints.weighty = 0.0 ;
		constraints.insets = new Insets(5, 5, 5, 5) ;
		
		JLabel label = new JLabel(
				sl.getText(ENTRY_FORMAT_EXPLANATION, 
						this.model.getSelectedFileInfo().getPath())) ;
		
		this.add(label) ;
		gridbag.setConstraints(label, constraints) ;
	}// buildTitle(GridBagLayout)
	
	/**
	 * Builds the entries for the analyzers, one per analyzer.
	 * Entries are displayed using the {@link ViewPlugInInfo} class.
	 * 
	 * @param	gridbag 
	 * 			layout manager used by this frame
	 * 
	 * @throws	UnknownKeyException 
	 * 			if the key for the explanation text was not found
	 */
	private void buildAnalyzers(GridBagLayout gridbag) throws UnknownKeyException {
		GridBagConstraints radioButtonConstraints, plugInCnstraints ;
		
		radioButtonConstraints = new GridBagConstraints() ;
		radioButtonConstraints.gridwidth = 1 ;
		radioButtonConstraints.anchor = GridBagConstraints.BASELINE_TRAILING ;
		radioButtonConstraints.weightx = 0.0 ;
		radioButtonConstraints.insets = new Insets(5, 50, 5, 5) ;
		
		plugInCnstraints = new GridBagConstraints() ;
		plugInCnstraints.gridwidth = GridBagConstraints.REMAINDER ;
		plugInCnstraints.anchor = GridBagConstraints.BASELINE_LEADING ;
		plugInCnstraints.weightx = 1.0 ;
		plugInCnstraints.insets = new Insets(5, 5, 5, 50) ;
		
		ButtonGroup group = new ButtonGroup() ;
		for(PlugInInfo analyzer : this.model.getKnownAnalyzers()) {
			try {
				boolean isSelected = analyzer.equals(this.selectedAnalyzer) ;
				final ViewPlugInInfo vpii = 
						new ViewPlugInInfo(this.model, analyzer, !isSelected) ;
				final JRadioButton radioButton = new JRadioButton() ;
				radioButton.setSelected(isSelected) ;
				radioButton.addItemListener(
						new RadioButtonListener(this, vpii, analyzer)) ;
				group.add(radioButton) ;
							
				this.add(radioButton) ;
				gridbag.setConstraints(radioButton, radioButtonConstraints) ;
				this.add(vpii) ;
				gridbag.setConstraints(vpii, plugInCnstraints) ;
			} catch (FileReadingException fre) {
				this.model.displayDebugInformation(fre) ;
			}// try
		}// for
	}// buildAnalyzers(GridBagLayout)
	
	/**
	 * Builds the validate button.
	 * 
	 * @param	gridbag 
	 * 			layout manager used by this frame
	 * 
	 * @throws	UnknownKeyException 
	 * 			if the key for the delete button text was not found
	 */
	private void buildButton(GridBagLayout gridbag) 
			throws UnknownKeyException {
		SwitchLanguage sl = SwitchLanguage.getInstance() ;
		GridBagConstraints constraints ;
		
		constraints = new GridBagConstraints() ;
		constraints.gridwidth = GridBagConstraints.REMAINDER ;
		constraints.anchor = GridBagConstraints.BASELINE ;
		constraints.weightx = 1.0 ;
		constraints.weighty = 0.0 ;
		constraints.insets = new Insets(5, 5, 5, 5) ;
		
		this.validate = new JButton(sl.getText(VALIDATE)) ;
		this.validate.setEnabled(this.selectedAnalyzer != null) ;
		this.validate.addActionListener(new ValidateListener(this)) ;
		
		this.add(this.validate) ;
		gridbag.setConstraints(this.validate, constraints) ;
	}// buildButton((GridBagLayout)
	
	/**
	 * Selects the given analyzer as the plug-in used to analyze the
	 * currently selected file.
	 * 
	 * @param	analyzer
	 * 			analyzer which will be used by the currently 
	 * 			selected file
	 */
	protected void selectAnalyzer(PlugInInfo analyzer) {
		this.selectedAnalyzer = analyzer ;
		this.validate.setEnabled(true) ;
	}// selectAnalyzer(PlugInInfo)
	
	/**
	 * Returns the model of this view.
	 * 
	 * @return	Model of this view
	 */
	protected Model getModel() {
		return this.model ;
	}// getModel()
	
	/**
	 * Listener for state changes of the radio buttons of this frame.
	 * Updates the selected analyzer accordingly.
	 * 
	 * @author	Schnell Michaël
	 * @version	1.0
	 */
	private class RadioButtonListener implements ItemListener {
		
		/**
		 * Parent frame of the component attached to this listener.
		 */
		protected EntryFormatSelectionFrame parent ;
		
		/**
		 * Component displaying the handled plug-in.
		 */
		protected ViewPlugInInfo view ;
		
		/**
		 * {@code PlugInInfo} handled by this listener.
		 */
		protected PlugInInfo info ;
		
		/**
		 * Sole constructor.
		 * 
		 * @param	parent
		 * 			parent frame of the component attached to this
		 * 			listener
		 * 
		 * @param	view
		 * 			component displaying the handled plug-in
		 * 
		 * @param	info
		 * 			{@code PlugInInfo} handled by this listener
		 */
		public RadioButtonListener(EntryFormatSelectionFrame parent,
				ViewPlugInInfo view, PlugInInfo info) {
			super();
			this.parent = parent ;
			this.view = view ;
			this.info = info ;
		}// CheckBoxListener(EntryFormatSelectionFrame, ViewPlugInInfo, PlugInInfo)
		
		/**
		 * Updates the selected analyzer.
		 * 
		 * @param	e
		 * 			event fetched by the listener
		 */
		@Override
		public void itemStateChanged(ItemEvent e) {
			try {
				if (e.getStateChange() == ItemEvent.SELECTED) {
					this.parent.selectAnalyzer(this.info) ;
					this.view.setIconIsGrayed(false) ;
				} else {
					this.view.setIconIsGrayed(true) ;
				}// if
			} catch (KameleonException ke) {
				this.parent.getModel().displayDebugInformation(ke) ;
			}// try
		}// itemStateChange(ActionEvent)
		
	}// class RadioButtonListener
	
	/**
	 * Listener for clicks on the validate button of this frame.
	 * Transfers the selected analyzer to model which will update
	 * the analyzer used by the currently selected file.
	 * 
	 * @author	Schnell Michaël
	 * @version	1.0
	 */
	private class ValidateListener implements ActionListener {
		
		/**
		 * Parent frame of the component attached to this listener.
		 */
		protected EntryFormatSelectionFrame parent ;

		/**
		 * /**
		 * Sole constructor.
		 * 
		 * @param	parent
		 * 			parent frame of the component attached to this
		 * 			listener
		 */
		public ValidateListener(EntryFormatSelectionFrame parent) {
			super() ;
			this.parent = parent ;
		}// ValidateListener(EntryFormatSelectionFrame)
		
		/**
		 * Sets the selected anaylzer as the analyzer used by the
		 * currently selected file. The parent frame is discarded
		 * afterwards.
		 * 
		 * @param	e
		 * 			event fetched by the listener
		 */
		@Override
		public void actionPerformed(ActionEvent e) {
			this.parent.model.setCurrentFileAnalyzer(
					this.parent.selectedAnalyzer) ;
			this.parent.dispose() ;
		}// actionPerformed(ActionEvent)
	
	}// class ValidateListener

}// class EntryFormatSelectionFrame